package com.hsqyz.esp32_led.netty;

import com.hsqyz.esp32_led.netty.cache.GlobalChannelCache;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * Netty服务器消息处理器
 * 
 * 该类负责处理与ESP32设备之间的通信，主要功能包括：
 * 1. 设备注册：处理设备的连接和注册请求
 * 2. 连接管理：处理设备的连接和断开事件
 * 3. 异常处理：处理通信过程中的异常情况
 * 
 * 继承自SimpleChannelInboundHandler<String>，专门处理字符串类型的消息
 */
@Slf4j
@Component
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
    
    /**
     * 全局通道缓存，用于管理所有设备连接
     */
    private final GlobalChannelCache channelCache;

    /**
     * 构造函数
     * 
     * @param channelCache 全局通道缓存对象，用于管理设备连接
     */
    public NettyServerHandler(GlobalChannelCache channelCache) {
        this.channelCache = channelCache;
    }

    /**
     * 处理接收到的消息
     * 
     * 根据消息类型进行不同的处理：
     * 1. 注册消息：处理设备注册请求
     * 
     * @param ctx 通道上下文
     * @param msg 接收到的消息内容
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) {
        log.info("Received message: {}", msg);
        
        if (msg.startsWith("register:")) {
            // 处理设备注册请求
            String clientId = msg.substring(9); // 去掉 "register:" 前缀
            channelCache.addChannel(clientId, ctx);
            log.info("Device registered with clientId: {}", clientId);
            ctx.writeAndFlush("registered\n");
        }
    }

    /**
     * 处理通道激活事件
     * 
     * 当客户端成功连接到服务器时调用此方法
     * 
     * @param ctx 通道上下文
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        log.info("Client connected: {}", ctx.channel().remoteAddress());
    }

    /**
     * 处理通道关闭事件
     * 
     * 当客户端断开连接时调用此方法，清理相关资源
     * 
     * @param ctx 通道上下文
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        log.info("Client disconnected: {}", ctx.channel().remoteAddress());
        channelCache.removeChannel(ctx);
    }

    /**
     * 处理通道异常事件
     * 
     * 当通道处理过程中发生异常时调用此方法
     * 记录错误日志并关闭通道
     * 
     * @param ctx 通道上下文
     * @param cause 异常原因
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        log.error("Channel exception caught", cause);
        ctx.close();
    }
} 